<template>
  <div class="background-row line">
    <label class="image-label">背景图</label>
    <tiny-input v-model="state.imgUrl" placeholder="请输入图片URL" @change="handleChangeImg"></tiny-input>
  </div>
  <div class="background-row line">
    <label class="size-label">大小</label>
    <tabs-group-configurator
      :options="BACKGROUND_SIZE_OPTIONS"
      :modelValue="state.sizeSelected"
      label-width="67"
      @update:modelValue="selectSize"
    ></tabs-group-configurator>
  </div>
  <div class="size-row">
    <div class="size-col">
      <label class="size-label">宽度</label>
      <input-select
        :modelValue="state.width"
        :suffixValue="state.widthSuffix"
        :options="UNIT_OPTIONS"
        :disabled="state.sizeSelected !== 'custom'"
        @input-change="sizeWidthChange"
        @select-change="suffixWidthChange"
      ></input-select>
    </div>
    <div class="size-col">
      <label class="size-label">高度</label>
      <input-select
        :modelValue="state.height"
        :suffixValue="state.heightSuffix"
        :options="UNIT_OPTIONS"
        :disabled="state.sizeSelected !== 'custom'"
        @input-change="sizeHeightChange"
        @select-change="suffixHeightChange"
      ></input-select>
    </div>
  </div>
  <position-origin class="background-row line" :is-top="true" @update="updateStyle"></position-origin>
  <div class="background-row tile-wrap">
    <label class="row-label">重复</label>
    <tabs-group-configurator
      :options="REPEAT_OPTIONS"
      :modelValue="state.repeat"
      label-width="50"
      @update:modelValue="selectRepeat"
    ></tabs-group-configurator>
  </div>
  <div class="background-row fixed-wrap">
    <label class="row-label">固定</label>
    <tabs-group-configurator
      :options="FIXED_OPTIONS"
      :modelValue="state.fixedSelected"
      label-width="98"
      @update:modelValue="selectFixed"
    ></tabs-group-configurator>
  </div>
</template>

<script setup>
/* metaService: engine.setting.styles.ImageSetting */
import { reactive, defineProps, defineEmits, onMounted } from 'vue'
import { Input as TinyInput } from '@opentiny/vue'
import { TabsGroupConfigurator } from '@opentiny/tiny-engine-configurator'
import PositionOrigin from './PositionOrigin.vue'
import InputSelect from '../inputs/InputSelect.vue'
import {
  BACKGROUND_PROPERTY,
  UNIT_OPTIONS,
  BACKGROUND_SIZE_OPTIONS,
  FIXED_OPTIONS,
  REPEAT_OPTIONS
} from '../../js/styleProperty'

const props = defineProps({
  style: {
    type: Object,
    default: () => ({})
  },
  effect: {
    type: String,
    default: 'dark'
  },
  placement: {
    type: String,
    default: 'top'
  }
})

const emit = defineEmits(['updateStyle'])

const state = reactive({
  checked: false,
  imgUrl: '',
  sizeSelected: 'custom',
  repeat: 'no-repeat',
  fixedSelected: 'scroll',
  width: 'Auto',
  widthSuffix: 'auto',
  height: 'Auto',
  heightSuffix: 'auto'
})

const updateStyle = (property) => {
  emit('updateStyle', property)
}

const handleChangeImg = (value) => {
  state.imgUrl = value
  updateStyle({ [BACKGROUND_PROPERTY.BackgroundImage]: `url(${value})` })
}

const selectSize = (value) => {
  if (value !== 'auto') {
    state.width = 'Auto'
    state.widthSuffix = 'auto'
    state.height = 'Auto'
    state.heightSuffix = 'auto'
  }
  state.checked = false
  state.sizeSelected = value
  updateStyle({ [BACKGROUND_PROPERTY.BackgroundSize]: value })
}

const isNum = (num) => {
  const reg = /^[0-9]+(.[0-9]+)?$/
  return reg.test(num)
}

const setBackgroundSize = () => {
  const isAutoWidth = state.width.toLocaleLowerCase() === 'auto'
  const isAutoHeight = state.height.toLocaleLowerCase() === 'auto'
  const width = isAutoWidth ? state.width.toLocaleLowerCase() : `${state.width.toLocaleLowerCase() + state.widthSuffix}`
  const height = isAutoHeight
    ? state.height.toLocaleLowerCase()
    : `${state.height.toLocaleLowerCase() + state.heightSuffix}`

  updateStyle({ [BACKGROUND_PROPERTY.BackgroundSize]: `${width} ${height}` })
}

const sizeWidthChange = (val) => {
  state.width = val
  if (state.widthSuffix === 'auto') {
    state.widthSuffix = isNum(val) ? 'px' : 'auto'
  }
  setBackgroundSize()
}

const suffixWidthChange = (val) => {
  state.widthSuffix = val
  if (state.widthSuffix === 'auto') {
    state.width = 'Auto'
  }
  setBackgroundSize()
}

const sizeHeightChange = (val) => {
  state.height = val
  if (state.heightSuffix === 'auto') {
    state.heightSuffix = isNum(val) ? 'px' : 'auto'
  }
  setBackgroundSize()
}

const suffixHeightChange = (val) => {
  state.heightSuffix = val
  if (state.heightSuffix === 'auto') {
    state.height = 'Auto'
  }
  setBackgroundSize()
}

const selectRepeat = (value) => {
  state.repeat = value
  updateStyle({ [BACKGROUND_PROPERTY.BackgroundRepeat]: value })
}

const selectFixed = (value) => {
  state.fixedSelected = value
  updateStyle({ [BACKGROUND_PROPERTY.BackgroundAttachment]: value })
}

onMounted(() => {
  const { styleObj } = props.style
  const backgroundImageStr = styleObj[BACKGROUND_PROPERTY.BackgroundImage]
  state.imgUrl = backgroundImageStr ? backgroundImageStr.substring(4, backgroundImageStr.length - 1) : ''
  state.fixedSelected = styleObj[BACKGROUND_PROPERTY.BackgroundAttachment]
  state.repeat = styleObj[BACKGROUND_PROPERTY.BackgroundRepeat]
  const sizeKeyword = ['cover', 'contain']
  const size = styleObj[BACKGROUND_PROPERTY.BackgroundSize] ?? ''
  state.sizeSelected = sizeKeyword.includes(size) ? size : 'custom'
  if (state.sizeSelected === 'custom') {
    const [width, height] = size.split(' ')
    const rLengthPercentage = /([+-]?\d*\.?\d+)(%|[a-z]+)?/
    const widthMatch = rLengthPercentage.exec(width)
    const heightMatch = rLengthPercentage.exec(height)
    if (widthMatch) {
      state.width = widthMatch[0]
      state.widthSuffix = widthMatch[1]
    } else {
      state.width = 'Auto'
      state.widthSuffix = 'auto'
    }
    if (heightMatch) {
      state.height = heightMatch[0]
      state.heightSuffix = heightMatch[1]
    } else {
      state.height = 'Auto'
      state.heightSuffix = 'auto'
    }
  }
  state.position = styleObj[BACKGROUND_PROPERTY.BackgroundPosition]
})
</script>

<style lang="less" scoped>
.image-content {
  display: grid;
  grid-template-columns: auto 1fr;
  row-gap: 8px;
}
.image-wrap {
  padding: 4px;
  width: 64px;
  height: 64px;
  border-width: 1px;
  box-sizing: border-box;
  border-style: solid;
  border: 1px dotted var(--te-styles-common-border-color);
  border-radius: 4px;
}
.image-inner {
  width: 100%;
  height: 100%;
  background-image: url(img/bgcModal.png);
  background-size: contain;
  background-repeat: no-repeat;
  background-position: 50% 50%;
}
.size-row {
  display: flex;
  padding: 6px 0;

  &:last-child {
    margin-bottom: 0;
  }
  .size-col {
    flex: 1;
    display: flex;
    align-items: center;
    &:not(:last-child) {
      margin-right: 8px;
    }
    .input-select {
      width: 70px;
    }
    .size-label {
      flex: 0 0 55px;
      margin-right: 6px;
      line-height: 28px;
      color: var(--te-styles-common-text-color-secondary);
    }
    &:last-child {
      .size-label {
        flex: 0 0 48px;
        margin-right: 10px;
        text-align: right;
      }
    }
  }
}
.choose-image {
  border-color: var(--te-styles-common-border-color);
  outline: 0px;
  cursor: default;
  user-select: none;
  padding: 0px;
  box-sizing: border-box;
  grid-column: 1 / -1;
  font-family: inherit;
  font-size: inherit;
  position: relative;
  display: flex;
  align-items: center;
  justify-content: center;
  height: 24px;
  border-radius: 4px;
  color: var(--te-styles-common-text-color-primary);
  border-width: 1px;
  border-style: solid;
  align-self: center;
  span {
    display: inline-block;
    overflow: hidden;
    text-overflow: ellipsis;
    white-space: nowrap;
  }
}
.image-size-item {
  cursor: default;
}
.dim-wrap {
  align-items: center;
  display: grid;
  gap: 4px 8px;
  grid-template-columns: 1fr 1fr;
  margin-top: 12px;
  & > span {
    justify-self: center;
  }
}
.tile-wrap {
  padding: 8px 0 4px;
  .svg-icon {
    font-size: 16px;
  }
}
.fixed-wrap {
  padding: 4px 0 8px;
}
.top {
  align-self: flex-start;
}
</style>
